package com.example.testplanetorbit

import android.content.Context
import android.graphics.*
import android.text.TextUtils
import android.util.Log
import com.example.testplanetorbit.OrbitData.Companion.INVALIDATE_TIMES1
import kotlin.math.abs

/**
 * 轨道上的标记点， 附带下面有文字显示
 */
class OvalTagDot(val tagData:Data) : BaseDot() {

    class Data(
        val id:String,
        val tagName:String,
        val count:String,
        val desc:String
    )

    var ovalR2 = 24.0f   //小球半径
//    var mOrbitPathLength = 0f
    var ovalPath2 : Path? = null
//    var mPos = FloatArray(2)
//    var mTan = FloatArray(2)
    var mPathMeasure2: PathMeasure? = null
    override var mDistance1 = 120f
    var ovalPaint2: Paint? = null

    private val tagPointF1 = FloatArray(2)
    val realPointF = FloatArray(2)
    var tagMatrix1 = Matrix()  //对文案进行变换的矩阵

//    var mStep1 = 0f

//    var lock = false

    var scaleRadio = 1f
    val OFFSET_BOTTOM = 64f //文字和上面的圆点之间的间隔

    fun dp2pxF(context: Context, dpValue: Float): Float {
        if (context != null) {
            val scale = context.resources.displayMetrics.density
            return dpValue * scale + 0.5f
        }
        return dpValue * 2 + 0.5f
    }
//    private var mInitDistanceRadio : Float = 0f
//    private var firstDrawOval = true

    override fun changeHorizontal(moveLeft:Boolean) {
        if (reverseDirection) {
            if (moveLeft) {
                mDistance1 -= (mOrbitPathLength * 0.01).toInt()
            } else {
                mDistance1 += (mOrbitPathLength * 0.01).toInt()
            }
        } else {
            if (moveLeft) {
                mDistance1 += (mOrbitPathLength * 0.01).toInt()
            } else {
                mDistance1 -= (mOrbitPathLength * 0.01).toInt()
            }
        }
    }

    val colors = arrayListOf<String>("#70E8BE", "#B97422", "#3706C5")
    var colorIndex = 0 //随机颜色

    override fun init(direction: Boolean) {
        colorIndex = (Math.random() * 3).toInt()
        if (ovalPaint2 == null) {
            ovalPaint2 = Paint()
            ovalPaint2?.isAntiAlias = true
            ovalPaint2?.color = Color.parseColor(colors[colorIndex])
            ovalPaint2?.style = Paint.Style.FILL
            ovalPaint2?.strokeWidth = 1f

        }
        this.reverseDirection = direction
    }

    private var reverseDirection = false

    override fun setPath(re21:RectF?, resetPath:Boolean) {
        if (re21 == null) {return}
        if (ovalPath2 == null || resetPath) {
            ovalPath2 = Path()
            if (reverseDirection) {
                ovalPath2?.addOval(re21!!, Path.Direction.CCW)
            }else {
                ovalPath2?.addOval(re21!!, Path.Direction.CW)
            }
            mPathMeasure2?.setPath(ovalPath2, false)
        }
        if (mPathMeasure2 == null) {
            mPathMeasure2 = PathMeasure(ovalPath2, false)
            mOrbitPathLength = mPathMeasure2?.length ?: 0f
            mStep1 = mOrbitPathLength * 1.0f / INVALIDATE_TIMES1
        }

        if (resetPath || mOrbitPathLength <= 0) {
            mOrbitPathLength = mPathMeasure2?.length ?: 0f
            mStep1 = mOrbitPathLength * 1.0f / OrbitData.INVALIDATE_TIMES1
        }
    }

    override fun drawOval1(canvas: Canvas?) {
        super.drawOval1(canvas)
//        if (firstDrawOval) {
//            mDistance1 = mOrbitPathLength * mInitDistanceRadio
//            firstDrawOval = false
//        }

        while (mDistance1 >= mOrbitPathLength) {
            mDistance1 = mDistance1 - mOrbitPathLength
        }
        while (mDistance1 < 0) {
            mDistance1 = mOrbitPathLength + mDistance1
        }

        mPathMeasure2?.getPosTan(mDistance1, mPos, mTan)

        ovalR2 = if (!reverseDirection) {
             if (mDistance1 > mOrbitPathLength * 1.0f / 2) {
                scaleRadio =
                    abs(mDistance1 - mOrbitPathLength * 3.0f / 4) / (mOrbitPathLength * 1.0f / 4)
                scaleRadio * (OrbitData.OVAL_TAG_R1 - OrbitData.OVAL_TAG_R1_MIN) + OrbitData.OVAL_TAG_R1_MIN
            } else {
                scaleRadio = 1f
                OrbitData.OVAL_TAG_R1
            }
        } else {
            if (mDistance1 < mOrbitPathLength * 1.0f / 2) {
                scaleRadio =
                    abs(mDistance1 - mOrbitPathLength * 1.0f / 4) / (mOrbitPathLength * 1.0f / 4)
                scaleRadio * (OrbitData.OVAL_TAG_R1 - OrbitData.OVAL_TAG_R1_MIN) + OrbitData.OVAL_TAG_R1_MIN
            } else {
                scaleRadio = 1f
                OrbitData.OVAL_TAG_R1
            }
        }

        ovalPaint2?.alpha  = (scaleRadio * (OrbitData.ALPHA_MAX - OrbitData.ALPHA_MIN) + OrbitData.ALPHA_MIN).toInt()

        val rLeft = mPos[0] - ovalR2
        val rRight = mPos[0] + ovalR2
        val rTop = mPos[1] - ovalR2
        val rBottom = mPos[1] + ovalR2
        tagPointF1[0] = mPos[0]
        tagPointF1[1] = mPos[1]

        canvas?.drawOval(rLeft, rTop, rRight, rBottom, ovalPaint2!!)
        if (!lock) {
            mDistance1 += mStep1
        }
    }

    var horizontalOffset = 0f
    var bottomOffset = 0f

    fun drawText(config: OrbitData.OvalConfig?, textPaint:Paint?, canvas: Canvas?) {
        if (config == null) {return }
        if (canvas == null) { return }
        if (textPaint == null) { return }
        if (TextUtils.isEmpty(tagData.tagName)) { return }

        tagMatrix1.reset()
        tagMatrix1.setTranslate(tagPointF1[0], tagPointF1[1])
        tagMatrix1.setRotate(config.degress?:0f, config.centerX, config.centerY)
        tagMatrix1.mapPoints(tagPointF1)
        val txtLength = textPaint.measureText(tagData.tagName)
        horizontalOffset = txtLength/2f
        realPointF[0] = tagPointF1[0]
        realPointF[1] = tagPointF1[1]

        canvas.drawText(tagData.tagName, tagPointF1[0] - txtLength/2, tagPointF1[1] + OFFSET_BOTTOM, textPaint)

        val offset = getFontHeight(textPaint) + OFFSET_BOTTOM
        val txtLength2 = textPaint.measureText(tagData.count)
        if (txtLength2 > txtLength) {
            horizontalOffset =  txtLength2/2f
        }
        canvas.drawText(tagData.count, tagPointF1[0] - txtLength2/2, tagPointF1[1] + offset, textPaint)
        bottomOffset = offset
    }

    val TAG = "OvalTagDot"
    /**
     * 点击位置是否位于当前标签点上
     */
    fun getClickRect(point:PointF) : Boolean {
        Log.d(TAG, "getClickRect::ovalR2 = $ovalR2, horizontalOffset = $horizontalOffset, bottomOffset = $bottomOffset, tagName= ${tagData.tagName}")
        val top = realPointF[1] - ovalR2
        val left = realPointF[0] - horizontalOffset
        val right = realPointF[0] + horizontalOffset
        val bottom = realPointF[1] + bottomOffset
        Log.d(TAG, "getClickRect::top = $top, left= $left, right = $right, bottom = $bottom, point = ${point.x},${point.y}")
        val retVal = (point.x in left..right && point.y in top..bottom)
        Log.d(TAG, "getClickRect::retVal = $retVal")
        return retVal
    }

    fun getFontHeight(paint : Paint?) : Float {
        return (paint?.fontMetrics?.descent?:0f) - (paint?.fontMetrics?.ascent?:0f)
    }

}